/**
  ******************************************************************************
  * @file    netconf.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    31-October-2011
  * @brief   Network connection configuration
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/tcp.h"
#include "lwip/tcp_impl.h"
#include "lwip/igmp.h"
#include "lwip/udp.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "ethernetif.h"
#include "lwipconfig.h"
#include "netconf.h"
#include "includes.h"

/* Private typedef -----------------------------------------------------------*/
#define MAX_DHCP_TRIES        4

/* Private define ------------------------------------------------------------*/
typedef enum 
{ 
  DHCP_START=0,
  DHCP_WAIT_ADDRESS,
  DHCP_ADDRESS_ASSIGNED,
  DHCP_TIMEOUT
} 
DHCP_State_TypeDef;
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
struct netif netif;
__IO uint32_t TCPTimer = 0;
__IO uint32_t ARPTimer = 0;
__IO uint32_t IPaddress = 0;

#ifdef USE_DHCP
uint32_t DHCPfineTimer = 0;
uint32_t DHCPcoarseTimer = 0;
DHCP_State_TypeDef DHCP_state = DHCP_START;
#endif

#ifdef LWIP_IGMP
uint32_t IGMPTimer = 0;
#endif

/* Private functions ---------------------------------------------------------*/
void LwIP_DHCP_Process_Handle(void);
/**
  * @brief  Initializes the lwIP stack
  * @param  None
  * @retval None
  */
void LwIP_Init(void)
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;

  /* Initializes the dynamic memory heap defined by MEM_SIZE.*/
  mem_init();

  /* Initializes the memory pools defined by MEMP_NUM_x.*/
  memp_init();

#ifdef USE_DHCP
  ipaddr.addr = 0;
  netmask.addr = 0;
  gw.addr = 0;
#else
  IP4_ADDR(&ipaddr, p_gSysUserRegs->MR_Para.IP_ADDR[0], p_gSysUserRegs->MR_Para.IP_ADDR[1], p_gSysUserRegs->MR_Para.IP_ADDR[2], p_gSysUserRegs->MR_Para.IP_ADDR[3]);
  IP4_ADDR(&netmask, p_gSysUserRegs->MR_Para.NETMASK_ADDR[0], p_gSysUserRegs->MR_Para.NETMASK_ADDR[1] , p_gSysUserRegs->MR_Para.NETMASK_ADDR[2], p_gSysUserRegs->MR_Para.NETMASK_ADDR[3]);
  IP4_ADDR(&gw, p_gSysUserRegs->MR_Para.GW_ADDR[0], p_gSysUserRegs->MR_Para.GW_ADDR[1], p_gSysUserRegs->MR_Para.GW_ADDR[2], p_gSysUserRegs->MR_Para.GW_ADDR[3]);
#endif

  /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
            struct ip_addr *netmask, struct ip_addr *gw,
            void *state, err_t (* init)(struct netif *netif),
            err_t (* input)(struct pbuf *p, struct netif *netif))
    
   Adds your network interface to the netif_list. Allocate a struct
  netif and pass a pointer to this structure as the first argument.
  Give pointers to cleared ip_addr structures when using DHCP,
  or fill them with sane numbers otherwise. The state pointer may be NULL.

  The init function pointer must point to a initialization function for
  your ethernet netif interface. The following code illustrates it's use.*/
  netif_add(&netif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);

  /*  Registers the default network interface.*/
  netif_set_default(&netif);

  /*  When the netif is fully configured this function must be called.*/
  netif_set_up(&netif);

  ARPTimer = localtime;
  TCPTimer = localtime;
  IPaddress = 0;
}

/**
  * @brief  Deinitializes the lwIP stack
  * @param  None
  * @retval None
  */
void LwIP_DeInit(void)
{

#ifdef USE_DHCP
	dhcp_stop(&netif);
#endif
	/*  When the netif link is down this function must be called.*/
	netif_set_down(&netif);
}

/**
  * @brief  Reinitializes the lwIP stack
  * @param  None
  * @retval None
  */
void LwIP_ReInit(void)
{
	struct ip_addr ipaddr;
	struct ip_addr netmask;
	struct ip_addr gw;

#ifdef USE_DHCP
	ipaddr.addr = 0;
	netmask.addr = 0;
	gw.addr = 0;
#else
	IP4_ADDR(&ipaddr, p_gSysUserRegs->MR_Para.IP_ADDR[0], p_gSysUserRegs->MR_Para.IP_ADDR[1], p_gSysUserRegs->MR_Para.IP_ADDR[2], p_gSysUserRegs->MR_Para.IP_ADDR[3]);
	IP4_ADDR(&netmask, p_gSysUserRegs->MR_Para.NETMASK_ADDR[0], p_gSysUserRegs->MR_Para.NETMASK_ADDR[1] , p_gSysUserRegs->MR_Para.NETMASK_ADDR[2], p_gSysUserRegs->MR_Para.NETMASK_ADDR[3]);
	IP4_ADDR(&gw, p_gSysUserRegs->MR_Para.GW_ADDR[0], p_gSysUserRegs->MR_Para.GW_ADDR[1], p_gSysUserRegs->MR_Para.GW_ADDR[2], p_gSysUserRegs->MR_Para.GW_ADDR[3]);
#endif
	
	/* Restart MAC interface */
	ETH_Start();

	netif_set_addr(&netif, &ipaddr , &netmask, &gw);

	/*  When the netif is fully configured this function must be called.*/
	netif_set_up(&netif);
	
	
	ARPTimer = localtime;
	TCPTimer = localtime;
	IPaddress = 0;
}

/**
  * @brief  Called when a frame is received
  * @param  None
  * @retval None
  */
void LwIP_Pkt_Handle(void)
{
  /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
  ethernetif_input(&netif);
}

/**
  * @brief  LwIP periodic tasks
  * @param  localtime the current LocalTime value
  * @retval None
  */
void LwIP_Periodic_Handle(__IO uint32_t localtime)
{
#if LWIP_TCP
  /* TCP periodic process every 250 ms */
	if(localtime != TCPTimer){
		if(localtime > TCPTimer){
			if (localtime - TCPTimer >= TCP_TMR_INTERVAL)
			{
				TCPTimer =  localtime;
				tcp_tmr();
			}
		}else{
			if((0xffffffff-TCPTimer+localtime+1) >= TCP_TMR_INTERVAL){
				TCPTimer =  localtime;
				tcp_tmr();
			}
		}
	}
#endif

#if LWIP_IGMP
	if(localtime != IGMPTimer){
		if(localtime > IGMPTimer){
			if (localtime - IGMPTimer >= IGMP_TMR_INTERVAL)
			{
				IGMPTimer = localtime;
				igmp_tmr();
			}
		}else{
			if((0xffffffff-IGMPTimer+localtime+1) >= IGMP_TMR_INTERVAL){
				IGMPTimer = localtime;
				igmp_tmr();
			}
		}
	}

#endif
  
  /* ARP periodic process every 5s */
	if(localtime != ARPTimer){
		if(localtime > ARPTimer){
			if ((localtime - ARPTimer) >= ARP_TMR_INTERVAL)
			{
				ARPTimer =  localtime;
				etharp_tmr();
			}
		}else{
			if((0xffffffff-ARPTimer+localtime+1) >= ARP_TMR_INTERVAL){
				ARPTimer =  localtime;
				etharp_tmr();
			}
		}
	}

#ifdef USE_DHCP
  /* Fine DHCP periodic process every 500ms */
	if(localtime != DHCPfineTimer){
		if(localtime > DHCPfineTimer){
			if (localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS)
			{
				DHCPfineTimer =  localtime;
				dhcp_fine_tmr();
				if ((DHCP_state != DHCP_ADDRESS_ASSIGNED)&&(DHCP_state != DHCP_TIMEOUT))
				{
					/* process DHCP state machine */
					LwIP_DHCP_Process_Handle();
				}
			}
		}else{
			if((0xffffffff - DHCPfineTimer + localtime+1) > = DHCP_FINE_TIMER_MSECS){
				DHCPfineTimer =  localtime;
				dhcp_fine_tmr();
				if ((DHCP_state != DHCP_ADDRESS_ASSIGNED)&&(DHCP_state != DHCP_TIMEOUT))
				{
					/* process DHCP state machine */
					LwIP_DHCP_Process_Handle();
				}
			}
		}
	}

  /* DHCP Coarse periodic process every 60s */
	if(localtime != DHCPcoarseTimer){
		if(localtime > DHCPcoarseTimer){
			if (localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS)
			{
				DHCPcoarseTimer =  localtime;
				dhcp_coarse_tmr();
			}
		}else{
			if((0xffffffff - DHCPcoarseTimer + localtime+1) >= DHCP_COARSE_TIMER_MSECS){
				DHCPcoarseTimer =  localtime;
				dhcp_coarse_tmr();
			}
		}
	}
#endif
}

#ifdef USE_DHCP
/**
  * @brief  LwIP_DHCP_Process_Handle
  * @param  None
  * @retval None
  */
void LwIP_DHCP_Process_Handle()
{
  struct ip_addr ipaddr;
  struct ip_addr netmask;
  struct ip_addr gw;
  uint8_t iptab[4];
  uint8_t iptxt[20];

  switch (DHCP_state)
  {
    case DHCP_START:
    {
      dhcp_start(&netif);
      IPaddress = 0;
      DHCP_state = DHCP_WAIT_ADDRESS;
    }
    break;

    case DHCP_WAIT_ADDRESS:
    {
      /* Read the new IP address */
      IPaddress = netif.ip_addr.addr;

      if (IPaddress!=0) 
      {
        DHCP_state = DHCP_ADDRESS_ASSIGNED;	

        /* Stop DHCP */
        dhcp_stop(&netif);
        STM_EVAL_LEDOn(LED1);
      }
      else
      {
        /* DHCP timeout */
        if (netif.dhcp->tries > MAX_DHCP_TRIES)
        {
          DHCP_state = DHCP_TIMEOUT;

          /* Stop DHCP */
          dhcp_stop(&netif);
#if 0
          /* Static address used */
          IP4_ADDR(&ipaddr, IP_ADDR0 ,IP_ADDR1 , IP_ADDR2 , IP_ADDR3 );
          IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
          IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
#endif
          IP4_ADDR(&ipaddr, p_gSysUserRegs->EE_Para.IP_ADDR[0], p_gSysUserRegs->EE_Para.IP_ADDR[1], p_gSysUserRegs->EE_Para.IP_ADDR[2], p_gSysUserRegs->EE_Para.IP_ADDR[3]);
          IP4_ADDR(&netmask, p_gSysUserRegs->EE_Para.NETMASK_ADDR[0], p_gSysUserRegs->EE_Para.NETMASK_ADDR[1] , p_gSysUserRegs->EE_Para.NETMASK_ADDR[2], p_gSysUserRegs->EE_Para.NETMASK_ADDR[3]);
          IP4_ADDR(&gw, p_gSysUserRegs->EE_Para.GW_ADDR[0], p_gSysUserRegs->EE_Para.GW_ADDR[1], p_gSysUserRegs->EE_Para.GW_ADDR[2], p_gSysUserRegs->EE_Para.GW_ADDR[3]);

          netif_set_addr(&netif, &ipaddr , &netmask, &gw);
        }
      }
    }
    break;
    default: break;
  }
}
#endif      

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
